package com.diandi.signature.timer;

import com.diandi.signature.batchrun.SignatureBatchRunService;
import com.diandi.signature.bean.contract.SignatureContract;
import com.diandi.signature.bean.proceessinfo.SignatureProcessLog;
import com.diandi.signature.bean.runbatch.SignatureBatchRunInfo;
import com.diandi.signature.contract.FddArchivesContractService;
import com.diandi.signature.contract.FddSignatureContractService;
import com.diandi.signature.enums.platfrom.BatchRunStatus;
import com.diandi.signature.enums.platfrom.BusinessStatus;
import com.diandi.signature.enums.platfrom.InterfactType;
import com.diandi.signature.enums.platfrom.PkgMsgStatus;
import com.diandi.signature.manager.contract.SignatureContractManager;

import com.diandi.signature.url.CreateTradeNo;
import com.diandi.signature.url.GsonUtil;
import com.diandi.signature.utils.FddContractSignatureTools;
import com.diandi.signature.utils.PackageParams;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by mxp on 2017/9/14.
 */
@Component
@EnableScheduling
public class SignTimerTask {
    private Logger logger = LoggerFactory.getLogger(SignTimerTask.class);

    @Autowired
    private FddSignatureContractService fddSignatureContractService;

    @Autowired
    private SignatureContractManager signatureContractManager;

    @Autowired
    private FddArchivesContractService fddArchivesContractService;

    @Autowired
    private SignatureBatchRunService signatureBatchRunService;

    /*@Autowired
    private MongoService mongoService;*/

    @Scheduled(cron = "${cron.expression.sign}")
    public void task(){

        String tradeNo = CreateTradeNo.createTradeNo("CT");

        Long sp1 = System.currentTimeMillis();
        logger.info("--["+tradeNo+"] contractTimer Start--");

        logger.debug("开始处理签章异常数据");
        //查询异常中断信息和无响应信息
        List<SignatureBatchRunInfo> toDoList = signatureBatchRunService.queryTask(Integer.valueOf(BatchRunStatus.初始化.getStatus()));


        Long sp2 = System.currentTimeMillis();
        logger.info("--["+tradeNo+"] step1 use times:"+(sp2-sp1)+"--");

        if (toDoList == null || toDoList.isEmpty()){
            logger.debug("无签章异常数据");
            return;
        }

        Map<String, String> returnMap = null;
        for (SignatureBatchRunInfo info : toDoList) {
            try {
                logger.debug("更改数据状态开始");
                info.setStatus(BatchRunStatus.已抽取.getStatus());
                signatureBatchRunService.updateBatchRunInfo(info);
                logger.debug("更改数据状态完成");

                logger.debug("开始处理签章");
                SignatureContract contract = new SignatureContract();
                contract.setContractCode(info.getContractCode());
                contract.setSignatureCode(info.getSignatureCode());
                contract.setUserId(info.getUserId());

                String platTradeNo = CreateTradeNo.createTradeNo("TM");
                Map<String, String> params = FddContractSignatureTools.string2Map(info.getPgkMsg());
                params.put("platTradeNo", platTradeNo);
                params.put("signatureCode",platTradeNo);

                Map queryGenerateMap = FddContractSignatureTools.genContractParamMap(params.get("contractType").toString(), params.get("contractParams").toString().replaceAll(" ", ""));
                queryGenerateMap.put("contractNo", info.getContractCode());

                logger.info("--rcv:platTradeNo:"+platTradeNo+":[合同生成->合同签章]: 开始处理--");

                Map<String, String > querySignatureMap = PackageParams.getContractSignatureMapByParms(info.getContractCode(), params);
                Map<String, String > rtnSignaturedMap = new HashMap<String, String >();
                returnMap = fddSignatureContractService.fddSignatureContractProcessTimer(contract,querySignatureMap,params,queryGenerateMap, info);

                SignatureProcessLog signatureProcessLog = new SignatureProcessLog();

                if (returnMap.containsKey("isArchived") && "1".equals(returnMap.get("isArchived"))){
                    //合同已归档，回调业务端
                    String result = signatureContractManager.callBusiness("1000", "操作成功", info.getContractCode(), info.getNotifyUrl(), params.get("merchantNo"));

                    if("SUCCESS".equals(result.toUpperCase())){
                        logger.debug("回调业务端成功");
                        //更新合同表为完成，过程主表为完成
                        signatureContractManager.notifySignatureUpdateProcessData(contract, String.valueOf(InterfactType.合同归档.getValue()));
                        //更新状态
                        logger.debug("更改数据状态");
                        info.setStatus(BatchRunStatus.已完成.getStatus());
                        signatureBatchRunService.updateBatchRunInfo(info);
                    }else{
                        //接收失败
                        //判断当前是否为最后一次请求
                        //插入跑批表数据，设置不同的状态
                        logger.debug("回调业务端失败");
                        info.setStatus(BatchRunStatus.异步通知初始化.getStatus());//异步通知失败
                        info.setRetryTimes(3);
                        signatureBatchRunService.insertBatchRunInfo(info);
                    }
                    continue;
                }

                if(!"success".equals(returnMap.get("result"))){
                    logger.info("--rcv:platTradeNo:"+platTradeNo+":[合同生成->合同签章]: 签章平台处理失败--");
                    //记录中间状态
                    continue;
                }

                logger.info("--rcv:platTradeNo:"+platTradeNo+":[合同生成->合同签章]: 完成处理--");

                /**
                 * 8.1 合同归档
                 */
                logger.info("--rcv:platTradeNo:"+platTradeNo+":[合同生成->合同归档]: 开始处理--");
                signatureContractManager.signatureUpdateProcessData(  contract, params , String.valueOf( InterfactType.合同归档.getValue() ));
                Map<String, String > queryArchivesMap = new HashMap<String, String >();
                Map<String, String > rtnArchivesMap = new HashMap<String, String >();
                queryArchivesMap.put("contractNo",info.getContractCode());
                queryArchivesMap.put("platTradeNO",platTradeNo);
                rtnArchivesMap = fddArchivesContractService.fddArchivesContract(queryArchivesMap);

                signatureContractManager.updateCompleteSignatureProcessData(contract, params , String.valueOf(InterfactType.合同归档.getValue()) ,rtnArchivesMap);

                /**更新返回给业务端的报文消息*/
                rtnSignaturedMap.put("tradeNo", platTradeNo);
                rtnSignaturedMap.put("returnMsg",returnMap.toString());
                rtnSignaturedMap.put("unnotifyMsg","");
                rtnSignaturedMap.put("passCode",params.get("passCode").toString());
                rtnSignaturedMap.put("userId",params.get("userId").toString());
                rtnSignaturedMap.put("downloadUrl", returnMap.get("download_url"));
                rtnSignaturedMap.put("viewpdfUrl", returnMap.get("viewpdf_url"));
                rtnSignaturedMap.put("contractCode", info.getContractCode());
                if (returnMap.containsKey("code") && returnMap.get("code").equals("1000")){
                    rtnSignaturedMap.put("status", String.valueOf(PkgMsgStatus.成功.getStatus()));
                } else {
                    rtnSignaturedMap.put("status", String.valueOf(PkgMsgStatus.处理失败.getStatus()));
                }
                rtnSignaturedMap.put("returnMsg", returnMap.toString());
                signatureContractManager.updateRvcPkgMsgInfo(rtnSignaturedMap);

//                mongoService.insert("fddSign", returnMap.toString(), params, platTradeNo, Long.parseLong(params.get("userId").toString()), returnMap.get("msg"), "应答报文");

                logger.info("--rcv:platTradeNo:"+platTradeNo+":[合同生成->合同归档]: 结束处理--");

                /**
                 * 9.1 处理返回给业务端的异步通知消息
                 */
                String result = signatureContractManager.callBusiness(rtnArchivesMap.get("code"), rtnArchivesMap.get("msg"),
                        info.getContractCode(), returnMap.get("download_url"), returnMap.get("viewpdf_url"), info.getNotifyUrl(),params.get("merchantNo"));

                if("SUCCESS".equals(result.toUpperCase())){
                    //更新合同表为完成，过程主表为完成
                    signatureProcessLog.setBusinessStatus(BusinessStatus.异步回执成功.getStatus());
                    signatureContractManager.notifySignatureUpdateProcessData(  contract,  String.valueOf( InterfactType.合同归档.getValue() ));
                    info.setStatus(BatchRunStatus.已完成.getStatus());
                    signatureBatchRunService.updateBatchRunInfo(info);
                }else{//接收失败
                    //判断当前是否为最后一次请求
                    signatureProcessLog.setBusinessStatus(BusinessStatus.异步回执失败.getStatus());
                    //插入跑批表数据
                    info.setStatus(BatchRunStatus.异步通知初始化.getStatus());//异步通知失败
                    info.setRetryTimes(3);
                    signatureBatchRunService.insertBatchRunInfo(info);
                }

                logger.info("--rcv:platTradeNo:"+platTradeNo+":[合同生成->合同渲染]: 完成返回给业务端--");

            } catch (Exception e){
                //更新重试次数
                info.setRetryTimes(info.getRetryTimes() - 1);
                info.setStatus(BatchRunStatus.初始化.getStatus());
                signatureBatchRunService.updateBatchRunInfo(info);

                e.printStackTrace();
            }
        }

        Long sp3 = System.currentTimeMillis();
        logger.info("--["+tradeNo+"] step2 use times:"+(sp3-sp2)+"--");
        logger.info("--["+tradeNo+"] End contractTimer , TotalTimes:"+(System.currentTimeMillis()-sp1)+"--");
    }

    public Map<String, String> getMapByJsonStr(String str){
        Map<String, String> returnMap = null;
        Map<String, String> contractMap = null;
        str = str.replaceAll(" ", "");

        String[] strs = str.split("contractParams=");
        String[] contractStrs = strs[1].split("}");
        String paramStr = (strs[0] + contractStrs[1]).replaceAll("\\{", "").replaceAll("}", "");
        String contractStr = contractStrs[0].replaceAll("\\{", "").replaceAll("}", "");
        if (StringUtils.isNotBlank(contractStr)){
            contractMap = getMapByStr(contractStr, ":");
        }

        if (StringUtils.isNotBlank(paramStr)){
            returnMap = getMapByStr(paramStr, "=");
        }

        if (!contractMap.isEmpty()){
            returnMap.put("contractParams", contractMap.toString());
        }

        return returnMap;
    }

    public  Map<String, String> getMapByStr(String param, String regex){
        if (StringUtils.isBlank(param)){
            return null;
        }
        Map<String, String> returnMap = new HashMap<String, String>();
        String[] params = param.split(",");
        for (String p : params) {
            String[] split = p.split(regex);
            if (split.length >= 2){
                returnMap.put(split[0], split[1]);
            }
        }
        return returnMap;
    }
}